/******************************************************************************
 Copyright (c) 2021-2023 Qualcomm Technologies International, Ltd.
 All Rights Reserved.
 Qualcomm Technologies International, Ltd. Confidential and Proprietary.

 REVISION:      $Revision: #9 $
******************************************************************************/
#include "cap_client_available_audio_context_req.h"
#include "cap_client_util.h"
#include "cap_client_csip_handler.h"
#include "cap_client_common.h"
#include "cap_client_debug.h"


void capClientSendDiscoverAvailableAudioContextCfm(CAP_INST *inst,
                                           CapClientGroupInstance *gInst,
                                           CapClientResult result)
{
    uint8 i;
    BapInstElement *iter;
    MAKE_CAP_CLIENT_MESSAGE(CapClientDiscoverAvailableAudioContextCfm);
    message->groupId = inst->activeGroupId;
    message->status = result;
    message->deviceContextLen = inst->deviceCount;

    message->deviceContext = (CapClientAvailableAudioContextInfo*)
                            CsrPmemZalloc(sizeof(CapClientAvailableAudioContextInfo)*message->deviceContextLen);

    if (gInst)
    {
        CAP_CLIENT_CLEAR_PENDING_OP(gInst->pendingOp);
        CAP_CLIENT_INFO("\n(CAP) DiscoverAvailableAudioContextCfm: BAP List Count: %d \n", gInst->bapList.count);
    }

    CAP_CLIENT_INFO("\n(CAP) DiscoverAvailableAudioContextCfm: Device Count: %d \n", inst->deviceCount);

    if(result == CAP_CLIENT_RESULT_SUCCESS && gInst)
    {
        iter = (BapInstElement*)(gInst->bapList.first);
        for(i = 0; i < message->deviceContextLen && iter; i++ )
        {
            message->deviceContext[i].cid = iter->bapHandle;
            message->deviceContext[i].context = iter->availableAudioContext;
            message->deviceContext[i].result = iter->recentStatus;
            iter = iter->next;
        }
    }

    CapClientMessageSend(inst->appTask, CAP_CLIENT_DISCOVER_AVAILABLE_AUDIO_CONTEXT_CFM, message);

}

void capClientSendDiscoverAvailableAudioContextReq(CAP_INST *inst,
                                          BapInstElement *bap,
                                          CapClientGroupInstance *gInst)
{
    BapInstElement *iter = bap;
    CsipInstElement *csip = NULL;

    for(; iter; iter = iter->next)
    {
        csip = CAP_CLIENT_GET_CSIP_ELEM_FROM_CID(gInst->csipList, iter->bapHandle);
        if(csip->recentStatus == CAP_CLIENT_RESULT_SUCCESS && 
                       csip->lock == CAP_CLIENT_LOCK_STATE_ENABLED)
        {
            inst->bapRequestCount++;
            BapDiscoverAudioContextReq(iter->bapHandle, BAP_PAC_AVAILABLE_AUDIO_CONTEXT);
        }
    }
}

void capClientHandleRemoteAvailableContextCfm(CAP_INST *inst,
                             BapDiscoverAudioContextCfm* cfm,
                             CapClientGroupInstance *gInst)
{
    BapInstElement *bap = CAP_CLIENT_GET_BAP_ELEM_FROM_PHANDLE(gInst->bapList, cfm->handle);

    /* Update Result*/
    inst->bapRequestCount--;
    bap->recentStatus = capClientGetCapClientResult(cfm->result, CAP_CLIENT_BAP);

    bap->availableAudioContext = (cfm->contextValue.sinkContext & 0x0000FFFF)
                                        | (cfm->contextValue.sourceContext << 16 & 0xFFFF0000);


    /* Send the Confirmation for all devices when request counter Hits zero*/
    if(inst->bapRequestCount == 0)
    {
        /* Is this Cordinated Set*/
        CsipInstElement* csip =
            (CsipInstElement*)((CsrCmnListElm_t*)(gInst->csipList.first));

        if(capClientIsGroupCoordinatedSet(gInst) && csip->lock == CAP_CLIENT_LOCK_STATE_ENABLED)
        {
            capClientSetCsisLockState(csip, &inst->csipRequestCount, FALSE);
        }
        else{
            /* Send BAP audio context cfm*/
            capClientSendDiscoverAvailableAudioContextCfm(inst, gInst, CAP_CLIENT_RESULT_SUCCESS);
        }
    }
}


void handleCapClientDiscoverAvailableAudioContextReq(CAP_INST *inst, const Msg msg)
{
    /*
     * First Check if the Group is A co-ordinated Set
     * Note: Group is a co ordinated Set if the CSIS instance has
     * setSize of more than 1 and has a valid CSIP handle
     * */

     CapClientGroupInstance *cap = NULL;
     CsipInstElement *csip  = NULL;
     CapClientInternalDiscoverAvailAudioContextReq *req =
                        (CapClientInternalDiscoverAvailAudioContextReq*)msg;
     CapClientResult result;

     /* if groupId is not same Switch the group
      *
      * Note: capClientSetNewActiveGroup sends CapClientActiveGroupChangeInd to the
      * application internally
      * */

     cap = capClientSetNewActiveGroup(inst, req->groupId, FALSE);


     /* If Group Id does not match with the list of cap groupiDs sned
      * Send CAP_RESULT_INVALID_GROUPID
      * */

     if (cap == NULL)
     {
         capClientSendDiscoverAvailableAudioContextCfm(inst, cap, CAP_CLIENT_RESULT_INVALID_GROUPID);
         CAP_CLIENT_ERROR("\n handleCapClientDiscoverAvailableAudioContextReq: invalid group \n");
         return;
     }

     result = capClientValidateCapState(cap->capState, req->type);

     if (result != CAP_CLIENT_RESULT_SUCCESS)
     {
         capClientSendDiscoverAvailableAudioContextCfm(inst, cap, result);
         CAP_CLIENT_INFO("\n handleCapClientDiscoverAvailableAudioContextReq: invalid state transition \n");
         return;
     }

     if(inst->streaming && req->groupId != inst->activeGroupId )
     {
          capClientSendDiscoverAvailableAudioContextCfm(inst, cap, CAP_CLIENT_RESULT_INVALID_OPERATION);
          CAP_CLIENT_INFO("\n handleCapClientDiscoverAvailableAudioContextReq: invalid Operation \n");
          return;
     }

     csip = (CsipInstElement*)((CsrCmnListElm_t*)(cap->csipList.first));

     /* Now check if the group is  a co-ordinated set*/

     if(csip == NULL)
     {
         CAP_CLIENT_ERROR("handleCapClientDiscoverAvailableAudioContextReq :CSIP NULL instance");
         return;
     }

     if(capClientIsGroupCoordinatedSet(cap))
     {
         /* Obtain Lock on the Devices */

         cap->pendingOp = CAP_CLIENT_BAP_DISCOVER_AUDIO_CONTEXT;

         if (csip->lock == CAP_CLIENT_LOCK_STATE_DISABLED)
         {
             capClientSetCsisLockState(csip, &inst->csipRequestCount, TRUE);
         }
         else
         {
             BapInstElement* bap = (BapInstElement*)((CsrCmnListElm_t*)(cap->bapList.first));
             capClientSendDiscoverAvailableAudioContextReq(inst, bap, cap);
         }
     }
     else
     {
         /* Start Discovery of the Published Capabilities*/

         BapInstElement *bap = (BapInstElement*)((CsrCmnListElm_t*)(cap->bapList.first));

         if(bap == NULL)
         {
             CAP_CLIENT_ERROR("handleCapClientDiscoverAvailableAudioContextReq : BAP NULL instance");
             return;
         }

         /* Note: At this point BAP service handle as well as CID shall
          * be valid and since this part of the code will only accessed
          * if there is only one device */

         inst->bapRequestCount++;
         BapDiscoverAudioContextReq(bap->bapHandle, BAP_PAC_AVAILABLE_AUDIO_CONTEXT);
     }
}
